\section{Designbeslissingen}
\label{sec:designbeslissingen}
Hier wordt een kort overzicht gegeven van enkele keuzes die gemaakt zijn bij de uitvoering van het project, en de redenering achter die keuzes.
\begin{itemize}

\item Alles meteen in Dubbele complexe precisie implementeren: Op het discussieforum werd vermeld dat het raadzaam was om in het begin enkel het re\"ele geval te behandelen. De methodes zouden dan echter grondig moeten worden aangepast om te werken met de complexe equivalenten. Het type van de argumenten is anders, en zelfs de betekenis van de argumenten kan anders zijn (bv \code{DGEEV} en \code{ZGEEV}).

\item Allocatie van de scratch space: De scratch space die gebruikt wordt bij het aanroepen van LAPACK routines moet groot genoeg zijn. In deel 1 werd voor deze scratch space een vector van grootte $10N$ genomen. De routine kan ook worden uitgevoerd met een argument ingesteld op -1 om de ideale grootte van de scratch space te bepalen, maar dit werd niet gedaan om tijd te besparen.
\newline In deel 2 werden de testen echter uitgebreid met grotere matrices, en hierbij bleek dat de scratch space onvoldoende groot was. De extra aanroep werd nu dus wel nodig om de ideale grootte te bepalen.

\item Als exacte oplossing wordt het resultaat van \code{expm} uit MATLAB genomen. Dit om een uniform resultaat te krijgen bij het vergelijken van de fout voor circulante en volle matrices. Indien als exacte oplossing voor circulante matrices bijvoorbeeld \code{ifft(exp(fft(c)))} wordt genomen berekend met MATLAB, is de fout merkelijk kleiner.

\item Alle methodes in een module \code{methods}: Een andere mogelijkheid is om zoals in bv LAPACK elk algoritme een aparte sourcefile te geven. Voor een project van deze kleine omvang is het echter overzichtelijker om alle methodes te bundelen in een module.

\item Aparte algoritmes voor het circulante geval: In dit project is er van elk algoritme een variant voor circulante matrices, met  eendimensionale input die de eerste kolom van de circulante matrix voorstelt. Een andere mogelijkheid is om een struct \code{Matrix} te defini\"eren, waarin wordt bijgehouden of deze al dan niet circulant is, eventueel de grootte, en \textit{allocatable} arrays van dimensie 1 en 2 om de data in bij te houden. Een algemene routine zou dan als argument een \code{Matrix} kunnen aanvaarden, en zelf bepalen of het de gewone of de circulante variant moet uitvoeren.
\newline Deze aanpak is niet gevolgd omwille van verschillende redenen: \begin{itemize} 
\item De aanpassingen aan de code van Deel 1 zouden extra tijd gevergd hebben. 
\item Een volle matrix en een kolom van een circulante matrix hebben weinig gemeenschappelijk om een generalisatie te rechtvaardigen, de algoritmes zijn immers totaal verschillend. 
\item In elk algoritme wordt een test gedaan om te kijken of de \code{Matrix} circulant is. Deze test is eigenlijk overbodig, want hij is al eens gebeurd bij het inlezen van de matrix.
\item Voor een externe gebruiker is het gemakkelijker indien de invoer standaard matrices of vectoren zijn, dit is ook de aanpak die door LAPACK gevolgd wordt.
\end{itemize}
Een voordeel van de aanpak met een struct \code{Matrix} is dat de code ordelijker wordt, en dat er minder methodes nodig zijn. Indien het aantal verschillende types matrices zou stijgen, zou deze aanpak wel te verkiezen zijn. Een oplossing zonder struct die het aantal publieke methodes vermindert is het defini\"eren van een interface \code{eig} of \code{eigqr}, die op basis van de (dimensie van) de argumenten beslist welk algoritme er gebruikt wordt.

\item Berekenen van de eigenwaarden: Omdat de LAPACK methodes niet allemaal naar behoren werkten, moest voor het eerste deel een methode \code{zgeeveigen} geschreven worden die de complexe eigenvectoren kon berekenen van een re\"ele inputmatrix. Toen de LAPACK bibliotheken wel werkten rees de vraag of de echte methode \code{ZGEEV} dan niet gebruikt moest worden. Uit testen bleek echter dat de eigen implementatie ongeveer drie keer sneller was (voor een 128x128 matrix). Dit kan verklaard worden uit het feit dat \code{ZGEEV} met complexe matrices werkt, terwijl \code{zgeeveigen} alle tussenliggende bewerkingen op re\"ele matrices uitvoert en enkel het resultaat aan complexe matrices toewijst.

\item De interface van de fft methodes: De standaardmethodes uit de FFTW bibliotheek geven als resultaat voor de fouriertransformatie van een re\"ele matrix van lengte $N$ een vector van lengte $N/2$ terug. Er zit immers redundantie in de uitkomst, de laatste $N/2$ waarden zijn de complex toegevoegde waarden van de eerste $N/2$. Er bestaat een mogelijkheid om dit uit te buiten in de algoritmes voor circulante matrices, door enkel de exponenti\"ele van de eerste $N/2$ waarden uit te rekenen. Dit zou een verbetering met maximaal factor 2 kunnen betekenen, maar wegens tijdsgebrek is dit niet ge\"implementeerd.
\item Loop unrolling van de taylor expansie: De lus in de taylorexpansie zou expliciet kunnen worden uitgeschreven, waarbij de lusconditie bijvoorbeeld slechts om de 10 iteraties gecontroleerd wordt. Dit zou de taylor-methodes versnellen, maar wegens tijdsgebrek en om de code ordelijk te houden is dit niet ge\"implementeerd.

\end{itemize}